package sk.ownage.p1.featurestore;

import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.List;

import android.os.Environment;
import android.util.Log;

public class LandmarkStore{

	public static final int DIRECTORY_MAX=256;
	private final String TAG="LandmarkStore";
	private File rootFolder;
	private static String actualLandmarkStoreName="";
	private String rootPath=Environment.getExternalStorageDirectory()+"/featureStore/landmarks";
	private static final String landmarkStoresPath=Environment.getExternalStorageDirectory()+"/featureStore/landmarkStores";
	private static LandmarkStore landmarkStore=new LandmarkStore();
	
	private LandmarkStore(){
		rootFolder=new File(rootPath);
		if(Environment.getExternalStorageDirectory().canWrite())
			if(!rootFolder.exists()){
				rootFolder.mkdirs();
			}
	}
	
	private LandmarkStore(String name){
		rootFolder=new File(landmarkStoresPath+"/"+name);
		if(Environment.getExternalStorageDirectory().canWrite())
			if(!rootFolder.exists()){
				rootFolder.mkdirs();
			}
		actualLandmarkStoreName=name;
	}

	public static LandmarkStore getInstance() {
		return landmarkStore;
	}
	
	public static void createLandmarkStore(String name){
		List<String> existingLandmarkStores=listLandmarkStores();
		for (String landmarkStoreName : existingLandmarkStores) {
			if(landmarkStoreName.equals(name))
				return;
		}
		File newLStoreFolder=new File(landmarkStoresPath+"/"+name);
		newLStoreFolder.mkdirs();
	}
	
	public static LandmarkStore getInstance(String name){
		List<String> existingLStores=listLandmarkStores();
		for (String landmarkStoreName : existingLStores) {
			if(landmarkStoreName.equals(name))
				return new LandmarkStore(name);
		}
		return null;
	} 
	
	public static List<String> listLandmarkStores(){
		List<String> result=new ArrayList<String>();
		File[] landmarkStoresDirectories=new File(landmarkStoresPath).listFiles();
		if(landmarkStoresDirectories!=null)
			for (int i = 0; i < landmarkStoresDirectories.length; i++) {
				if(!landmarkStoresDirectories[i].isFile()){
					result.add(landmarkStoresDirectories[i].getName());
				}
			}
		return result;
	}
	
	public static void deleteLandmarkStore(String name){
		if(actualLandmarkStoreName.equals(name))
			return;
		List<String> existingLandmarkStores=listLandmarkStores();
		for (String landmarkStoreName : existingLandmarkStores) {
			if(landmarkStoreName.equals(name))
				DeleteDirectoryRecursively(new File(landmarkStoresPath+"/"+name));
		}
	} 
	
	public Landmark newLandmark(){
		return new Landmark();
	}
	/* return list of all ids of all landmarks in this LandmarkStore directory*/
	public List<Landmark> getLandmarks(){
		return getFilteredLandmarks("","");
	}
	
	/*return list of all ids of all landmarks in this LandmarkStore directory with same activity*/
	public List<Landmark> getLandmarks(String category){
		return getFilteredLandmarks(category,"");
	}

	/*return list of all ids of all landmarks in this LandmarkStore directory with same activity and name*/
	public List<Landmark> getLandmarks(String category,String name){
		return getFilteredLandmarks(category,name);
	}
	
	private List<Landmark> getFilteredLandmarks(String category,String name){
		List<Landmark> result=new ArrayList<Landmark>();
		File landmarksFolder= new File(landmarkStoresPath+"/"+actualLandmarkStoreName+"/landmarks");
		if(!landmarksFolder.exists())
			landmarksFolder.mkdirs();
		//File[] landmarksDirectories=rootFolder.listFiles();
		File[] landmarksDirectories=landmarksFolder.listFiles();
		for (int i = 0; i < landmarksDirectories.length; i++) {
			if(!landmarksDirectories[i].isFile()){
				File[] landmarks=landmarksDirectories[i].listFiles();
				int folderId=Integer.parseInt(landmarksDirectories[i].getName())*DIRECTORY_MAX;
				for (int j = 0; j < landmarks.length; j++) {
					String[] landmarkFileName=landmarks[j].getName().split("\\.");
					int landmarkId=Integer.parseInt(landmarkFileName[0]);
					int Id=folderId + landmarkId;
					if(category!=""){
						LandmarkReader lr= new LandmarkReader(Id,landmarkStoresPath+"/"+actualLandmarkStoreName+"/landmarks");
						try {
							if(name!=""){
								if(lr.readName().equals(name) && lr.readCategory().equals(category))
									result.add(new Landmark(Id,landmarkStoresPath+"/"+actualLandmarkStoreName));
							}else{
								lr.readName();
								if(lr.readCategory().equals(category))
									result.add(new Landmark(Id,landmarkStoresPath+"/"+actualLandmarkStoreName));
							}
							lr.stopReader();
						} catch (Exception e) {
							Log.d(TAG,e.toString());
						}
					}else{
						result.add(new Landmark(Id,landmarkStoresPath+"/"+actualLandmarkStoreName));
					}
				}
			}
		}
		return (result.size()>0)?result:null;
	}
	
	//objekt typu landmark je vstupom
	public boolean deleteLandmark(Landmark landmark) throws Exception{
		int folderId = landmark.getID() / DIRECTORY_MAX;
		int fileId = landmark.getID() % DIRECTORY_MAX;;
		String folderPath = (((folderId / 100) > 0) ? "" : "0")
				+ (((folderId / 10) > 0) ? "" : "0") + folderId;
		String filePath = (((fileId / 100) > 0) ? "" : "0")
				+ (((fileId / 10) > 0) ? "" : "0") + fileId;
		//File landmarkToDelete=new File(rootPath+"/"+folderPath+"/"+filePath+".bin");
		File landmarkToDelete=new File(landmarkStoresPath+"/"+actualLandmarkStoreName+"/landmarks"+"/"+folderPath+"/"+filePath+".bin");
		if(landmark.getID()==loadMaxId()+1)
			throw new Exception("You cannot delete landmark that you are actualy recording!");
		if(!landmarkToDelete.exists())
			throw new Exception("Landmark not exists!");
		DeleteDirectoryRecursively(new File(landmarkStoresPath+"/"+actualLandmarkStoreName+"/geometry"+"/"+folderPath+"/"+filePath));
		return landmarkToDelete.delete();
	}
	
	private int loadMaxId(){
		//File maxIdpath=new File(rootPath+"/"+"maxId.bin");
		File maxIdpath=new File(landmarkStoresPath+"/"+actualLandmarkStoreName+"/landmarks"+"/maxId.bin");
		int result=-1;
		if(maxIdpath.exists())
		try {
			FileInputStream fis = new FileInputStream(maxIdpath);
			ObjectInputStream is = new ObjectInputStream(fis);
			result=is.readInt();
			is.close();
		} catch (Exception e) {
			Log.d(TAG, e.toString());
		}
		return result;
	}
	
	private static void DeleteDirectoryRecursively(File fileOrDirectory) {
	    if (fileOrDirectory.isDirectory())
	        for (File child : fileOrDirectory.listFiles())
	            DeleteDirectoryRecursively(child);
	        fileOrDirectory.delete();
	}
}
